﻿namespace ChinaUnicom.Web
{
    using System.Linq;
    using System.Collections.Generic;
    using HtmlAgilityPack;
    using ChinaUnicom.Models;

    class HtmlParser : IHtmlParser
    {
        static char[] TrimChars = new[] { ' ', '\r', '\t', '\n', '：', ':' };

        // static string[] ReplaceChars = new[] { "\r", "\t", "\n", "：", ":" };

        public ItemCollection Parse(string html, InfoType type)
        {
            switch (type)
            {
                case InfoType.Client:
                    return ParseClientInfo(html);
                case InfoType.Fee:
                    return ParseFeeInfo(html);
                case InfoType.Package:
                    return ParsePackageInfo(html);
                default:
                    return null;
            }
        }

        public string Failed(string html)
        {
            string tips = "系统异常,操作失败！";

            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(html);

            var span = doc.DocumentNode.Descendants("span").FirstOrDefault(x => x.InnerText.Contains("【温馨提示】"));

            if (span != null)
            {
                var tipsNode = span.ParentNode.Descendants("span").FirstOrDefault(x => x.InnerText.Contains("&nbsp;&nbsp;&nbsp;&nbsp;"));
                if (tipsNode != null)
                {
                    tips = tipsNode.InnerText.Replace("&nbsp;", string.Empty).Trim(TrimChars);
                }
            }

            return tips;
            /*
	        <span>【温馨提示】</span>
	        <br />
	        <span>&nbsp;&nbsp;&nbsp;&nbsp;系统异常,操作失败！</span>

            <span>【温馨提示】</span>
            <br />
            <span>&nbsp;&nbsp;&nbsp;&nbsp;系统异常,操作失败！系统正忙，请稍后再试。</span>

            <span>【温馨提示】</span>
            <br />
            <span>&nbsp;&nbsp;&nbsp;&nbsp;尊敬的用户，每月最后一天22:00至次日09:00是系统出账期，请您在出账期之后进行操作。</span>
            */
        }

        ItemCollection ParseClientInfo(string html)
        {
            ItemCollection items = new ItemCollection();

            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(html.Replace("&nbsp;", string.Empty));
            var contents = doc.DocumentNode.Descendants("div").Where(x => x.Attributes["class"] != null && x.Attributes["class"].Value == "mrlf2").ToList();

            // base info
            string name = string.Empty;
            foreach (HtmlNode node in contents[0].ChildNodes)
            {
                if (node.Name == "#text" && name == string.Empty)
                {
                    name = node.InnerText.Trim(TrimChars).Replace("：", string.Empty);
                }
                else if (node.Name == "span" && name != string.Empty)
                {
                    items.Add(new Item { Name = name, Value = node.InnerText.Trim(TrimChars).Replace("：", string.Empty) });
                    name = string.Empty;
                }
            }

            // more info
            name = string.Empty;
            foreach (HtmlNode node in contents[1].ChildNodes)
            {
                if (node.Name == "#text" && name == string.Empty)
                {
                    name = node.InnerText.Trim(TrimChars).Replace("：", string.Empty);
                }
                else if (node.Name == "span" && name != string.Empty)
                {
                    items.Add(new Item { Name = name, Value = node.InnerText.Trim(TrimChars).Replace("：", string.Empty) });
                    name = string.Empty;
                }
            }
            
            return items;
        }

        ItemCollection ParseFeeInfo(string html)
        {
            ItemCollection items = new ItemCollection();

            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(html.Replace("&nbsp;", string.Empty));

            var node = doc.DocumentNode;// .ChildNodes.Select(x=>x.Attributes["class"].Value == "nrong")

            var div = node.Descendants("div").Where(x => x.Attributes["class"] != null && x.Attributes["class"].Value == "nrong").FirstOrDefault();

            if (div != null)
            {
                var p = div.Descendants("p").SingleOrDefault();

                int step = -1;

                if (p != null)
                {
                    string name = string.Empty;
                    foreach (HtmlNode n in p.ChildNodes)
                    {
                        if (n.Name == "#text" && n.InnerText.Trim(TrimChars).Contains("当月话费信息"))
                        {
                            step = 0;
                            continue;
                        }
                        else if (n.Name == "#text" && n.InnerText.Trim(TrimChars).Contains("当月话费明细"))
                        {
                            step = 1;
                            continue;
                        }

                        if (step >= 0)
                        {
                            if (n.Name == "#text" && string.IsNullOrEmpty(name))
                            {
                                name = n.InnerText.Trim(TrimChars).Replace("：", string.Empty);
                            }

                            if (n.Name == "span" && !string.IsNullOrEmpty(name))
                            {
                                items.Add(new Item { Name = name, Value = n.InnerText.Trim(TrimChars).Replace("：", string.Empty) });
                                name = string.Empty;
                            }
                        }
                    }
                }
            }

            return items;
        }

        ItemCollection ParsePackageInfo(string html)
        {
            ItemCollection items = new ItemCollection();

            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(html.Replace("&nbsp;", string.Empty));

            var node = doc.DocumentNode;// .ChildNodes.Select(x=>x.Attributes["class"].Value == "nrong")

            var divs = node.Descendants("div").Where(x => x.Attributes["class"] != null && x.Attributes["class"].Value == "nrong").ToList();

            var basic = divs[0].Descendants("p").FirstOrDefault();
            if (basic != null)
            {
                string name = string.Empty;
                foreach (HtmlNode span in basic.ChildNodes.Where(x => x.Name == "span"))
                {
                    if (string.IsNullOrEmpty(name))
                    {
                        name = span.InnerText.Trim(TrimChars).Replace("：", string.Empty);
                    }
                    else
                    {
                        items.Add(name, span.InnerText.Trim().Replace("：", string.Empty));
                        name = string.Empty;
                    }
                }
            }

            Item more = null;
            foreach (HtmlNode inode in divs[1].ChildNodes)
            {
                if (inode.Name == "#text" && more == null)
                {
                    var n = inode.InnerText.Trim(TrimChars);
                    if (!string.IsNullOrEmpty(n))
                    {
                        more = new Item();
                        more.Name = inode.InnerText.Trim(TrimChars).Replace("：", string.Empty);
                        items.Add(more);
                    }
                }

                if (inode.Name == "span")
                {
                    more.Value = inode.InnerText.Trim(TrimChars).Replace("：", string.Empty);
                }

                if (inode.Name == "div" && inode.Attributes["class"] != null && inode.Attributes["class"].Value == "mrlf")
                {
                    more.Details.Add(GetPackageinfosChildren(inode));
                    more = null;
                }
            }

            return items;
        }

        static IEnumerable<Item> GetPackageinfosChildren(HtmlNode node)
        {
            foreach (HtmlNode item in node.ChildNodes)
            {
                if (item.Name == "#text")
                {
                    var texts = item.InnerText.Trim(TrimChars).Split(new[] { '：' });
                    if (texts.Length >= 2)
                    {
                        var i = new Item();
                        i.Name = texts[0].Trim(TrimChars);
                        i.Value = texts[1].Trim(TrimChars);

                        yield return i;
                    }
                }
            }
        }
    }
}
